﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.DataVisualization.Charting;
using System.Windows.Controls.DataVisualization;
using System.Windows.Data;
using System.Windows.Media;
using Porownywarka;
using Porownywarka.Interfejsy;
using Porownywarka.Sortowanie;

namespace PorownywarkaGUI
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public Porownywarka<uint> Porownaj { get; set; }
        public List<AsyncObservableCollection<KeyValuePair<string, int>>> Collection { get; set; } 

        private List<ISortMethod<uint>> metody;
        private List<string> nazwyMetod; 
        private uint[] dane;
        private Random rand = new Random();
        private bool running;
        private Thread t;

        private int kwant;
        private int rozmiar;

        public MainWindow()
        {
            InitializeComponent();
        }

        private void Play_Click(object sender, RoutedEventArgs e)
        {
            if(running)
            { 
                t.Abort();
                Collection = null;

                Play.Content = "start";
                wykres.Series.Clear();
                running = false;
                Paused.IsEnabled = false;
                Paused.Content = "pause";
                single.Text = String.Empty;

            } else
            {
                Collection = new List<AsyncObservableCollection<KeyValuePair<string, int>>>();
                metody = new List<ISortMethod<uint>>();
                nazwyMetod = new List<string>();

                if (bubblesort.IsChecked.Value)
                {
                    metody.Add(new BubbleSort<uint>());
                    nazwyMetod.Add(bubblesort.Content.ToString());
                    Collection.Add(new AsyncObservableCollection<KeyValuePair<string, int>>());
                }

                if (heapsort.IsChecked.Value)
                {
                    metody.Add(new HeapSort<uint>());
                    nazwyMetod.Add(heapsort.Content.ToString());
                    Collection.Add(new AsyncObservableCollection<KeyValuePair<string, int>>());
                }

                if (quicksort.IsChecked.Value)
                {
                    metody.Add(new QuickSort<uint>());
                    nazwyMetod.Add(quicksort.Content.ToString());
                    Collection.Add(new AsyncObservableCollection<KeyValuePair<string, int>>());
                }

                if (mergesort.IsChecked.Value)
                {
                    metody.Add(new MergeSort<uint>());
                    nazwyMetod.Add(mergesort.Content.ToString());
                    Collection.Add(new AsyncObservableCollection<KeyValuePair<string, int>>());
                }

                if (countingsort.IsChecked.Value)
                {
                    metody.Add(new CountingSort());
                    nazwyMetod.Add(countingsort.Content.ToString());
                    Collection.Add(new AsyncObservableCollection<KeyValuePair<string, int>>());
                }


                //tutaj dopiero bedzie waidomo ile serii;

                if (!int.TryParse(iloscdanych.Text, out rozmiar))
                    throw new Exception("BŁĄD ilosc dancyh");

                if (!int.TryParse(kwantczasu.Text, out kwant))
                    throw new Exception("BŁĄD kwant czasu");

                t = new Thread(() => { Startuj(); });
                t.Start();

                running = true;
                Play.Content = "stop";
            }
        }

        private void Startuj()
        {

            Action b = () =>
                           {
                               dane = new uint[rozmiar];

                               for (int i = 0; i < rozmiar; i++)
                                   dane[i] = (uint)rand.Next(100);

                           };

                Dispatcher.Invoke(b, null);

                Porownaj = new Porownywarka<uint>(metody.ToArray(), dane, Collection);
                Porownaj.Finished += new MyEventHandler(Porownaj_Finished);

                for (int i = 0; i < metody.Count; i++)
                {
                    int k = i;

                    Dispatcher.Invoke(new Action(() =>
                                                     {
                                                         Style style = new Style(typeof(AxisLabel));
                                                         style.Setters.Add(new Setter(AxisLabel.VisibilityProperty, Visibility.Collapsed));

                                                         Style style2 = new Style(typeof(LineDataPoint));
                                                         style2.Setters.Add(new Setter(LineDataPoint.TemplateProperty, null));
                                                         style2.Setters.Add(new Setter(LineDataPoint.BackgroundProperty, new SolidColorBrush(Color.FromRgb((byte)rand.Next(256), (byte)rand.Next(256), (byte)rand.Next(256)))));


                                                         LineSeries series = new LineSeries();
                                                         series.Title = nazwyMetod[k];
                                                         series.DataPointStyle = style2;
                                                         series.IndependentValueBinding = new Binding("Key");
                                                         series.IndependentAxis = new CategoryAxis { Orientation = AxisOrientation.X,  MajorTickMarkStyle = null,ShowGridLines = false};
                                                         series.DependentValueBinding = new Binding("Value");
                                                         series.ItemsSource = Collection[i];
                                                         wykres.Series.Add(series);
                                                     }), null);
                }

                Dispatcher.Invoke(new Action(() => { Paused.IsEnabled = true; }));
                Porownaj.Start(kwant);
            
        }

        void Porownaj_Finished(object sender, MyEventArgs e)
        {
            Dispatcher.Invoke(new Action(() =>
                                             {
                                                 Paused.IsEnabled = false;
                                             }));



            if(MessageBox.Show("Zakończyłem! Czy chcesz poznać dokładniejsze czasy sortowań?", "Koniec porównywania", MessageBoxButton.YesNo) == MessageBoxResult.Yes)
            {
                Stopwatch zegarek = new Stopwatch();

                for (int i = 0; i < metody.Count; i++)
                {
                    int k = i;
                    zegarek.Reset();

                    zegarek.Start();
                    metody[i].Sort(dane);
                    zegarek.Stop();
                    Dispatcher.Invoke(
                        new Action(() => { single.Text += " " + nazwyMetod[k] + " : " + zegarek.ElapsedMilliseconds + "[ms]"; }));
                }


            }


        }

        private void Paused_Click(object sender, RoutedEventArgs e)
        {
            if(Porownaj.Paused)
            {
                Porownaj.Continue();
                Paused.Content = "pause";
            } else
            {
                Porownaj.Pause();
                Paused.Content = "continue";   
            }
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            Application.Current.Shutdown();
        }
    }
}
